using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports; //追加 シリアルポートコンポーネント用
namespace _102_COM_test
{
public partial class Form1 : Form
{
int CommandNum,CommandNum2;
int Flag_EchoOff;
int LedMode = 0;
string str2;
string str3;
string str4;
string strMacAdrs;
string strMacAdrsType;
char AlternativeChar = '0'; //交互文字型フラグ
Byte[] OUTBuffer = new byte[20]; //送信バッファー
Byte[] INBuffer = new byte[20]; //受信バッファー
//文字を変換するクラスを宣言
Encoding encSjis = Encoding.GetEncoding("shift-jis");
Encoding encUni = Encoding.GetEncoding("unicode");
delegate void ReceiveDelegate(string str);//デリゲート宣言
public Form1()
{
InitializeComponent();
SendDataBtn.Visible = false;
ManuSendBtn.Visible = false;
SendDataCBox.Visible = false;
LedBtn.BackColor = Color.DarkGray;//ダークグレー色
pictureBox1.Visible = false;
pictureBox2.Visible = true;
OffSw_pictureBox.Visible = true; //SW オフ画像表示
OnSw_pictureBox.Visible = false; //SW オン画像表示
//接続状態表示ランプの表示
pictureBox5.Image = new Bitmap(pictureBox5.Width, pictureBox5.Height);//Widthxhight: 75x75 //pictureBox1のイメージデータのオブジェクト生成
Graphics g = Graphics.FromImage(pictureBox5.Image); //イメージからグラフィックスを作成
g.FillEllipse(Brushes.Gray, 0, 0, 50, 50);//灰色塗りつぶし 基点(0,0) 幅×高さ:50×50
VR_progressBar.Value = 0;
SendDataCBox.Items.Clear();
SendDataCBox.Items.Add("+//Echo OnOff");
SendDataCBox.Items.Add("SF,1//Initialize RN4020");
SendDataCBox.Items.Add("SR,80000000//Set Central Mode");
SendDataCBox.Items.Add("R,1//Reboot");
SendDataCBox.Items.Add("D//Device Info");
SendDataCBox.Items.Add("F//Start Scan");
SendDataCBox.Items.Add("X//Stop Scan");
SendDataCBox.Items.Add("E//Establish Connection");
SendDataCBox.Items.Add("Z");
SendDataCBox.Items.Add("Z//Stop Connecting");
SendDataCBox.Items.Add("LS//List Server Services");
SendDataCBox.Items.Add("LC//List Client Services");
SendDataCBox.Items.Add("CHW,000B,4041424344454647484940414243444546474849//Write value of client handle");
SendDataCBox.Items.Add("CHW,000B,45464748//Write EFGH value of client handle");
SendDataCBox.Items.Add("CHW,000B,494A4B4C//Write IJKL value of client handle");
SendDataCBox.Items.Add("CHR,000B//Read value of client handle");
SendDataCBox2.Items.Clear();
SendDataCBox2.Items.Add("Japan");
SendDataCBox2.Items.Add("America");
SendDataCBox2.Items.Add("U.K.");
SendDataCBox2.Items.Add("France");
SendDataCBox2.Items.Add("How are you ?");
SendDataCBox2.SelectedIndex = 0;
string[] PortList = SerialPort.GetPortNames();
foreach (string PortName in PortList)
{
ComCBox.Items.Add(PortName);
}
if (ComCBox.Items.Count > 0)
{
ComCBox.SelectedIndex = 0;
}
}
private void ConnectBtn_Click(object sender, EventArgs e)
{
if (serialPort1.IsOpen == true) // シリアルポートがオープンしている場合
{
serialPort1.Close(); //COMポートを閉じる
}
try
{
serialPort1.PortName = ComCBox.SelectedItem.ToString();
//serialPort1.PortName = "COM3"; //COM1 ポート使用
//serialPort1.PortName = "COM5"; //COM1 ポート使用
//再設定:必須
serialPort1.BaudRate = 115200; //9600bps
serialPort1.Parity = System.IO.Ports.Parity.None; //パリティなし
serialPort1.DataBits = 8; //データ長 8ビット
serialPort1.StopBits = System.IO.Ports.StopBits.One; //ストップビット 1
serialPort1.ReadTimeout = 500; //500mse 読み込みタイムアウト時間
serialPort1.WriteTimeout = 500; //500msec書き込みタイムアウト時間
serialPort1.Open();//シリアルポートオープン
SendDataBtn.Visible = true;
ManuSendBtn.Visible = true;
SendDataCBox.Visible = true;
}
catch (Exception ex)
{
DialogResult result = MessageBox.Show
(ex.Message + "\n" + "COMポートがひらけません。\n" +
" <対応例>\n" +
" ・COMポート変更\n" +
" ・COMポートを接続してから本アプリケーションを再起動");
SendDataBtn.Visible = false;
ManuSendBtn.Visible = false;
SendDataCBox.Visible = false;
}
}
private void SendData(string myString)
{
if (!myString.EndsWith("\r")) myString += "\r"; //改行が無かったら \rを追加する
Byte[] byteArry = encSjis.GetBytes(myString); //'送信文字をShift-jisに変換してをByte配列に格納
serialPort1.Write(byteArry, 0, byteArry.Length); //送信
}
private void SendDataBtn_Click(object sender, EventArgs e) //自動コマンド送信ボタン
{
serialPort1.DiscardInBuffer(); //受信バッファのデータクリア
SendData("+//Echo OnOff");
timer1.Interval = 3000;
timer1.Enabled = true;
CommandNum = 1;
}
//削除条件を定義するデリゲート
static bool strCheck(string str) //,,,,が4個以上のみ摘出
{
bool judge;
int startPosi = 0;
int endPosi = 0;
int Num = 0;
do
{
endPosi = str.IndexOf(",", startPosi); //label3.Text = "指定文字列が ","x 4個以下の要素を削除の場合"";
if (endPosi >= 0)
{
startPosi = endPosi + 1;
Num++; //指定文字列の数をカウント
}
} while (endPosi >= 0);
if (Num <= 3)
{
judge = true; // , が4個以下の要素を削除 //要素削除
}
else
{
judge = false; //要素 非削除
}
return judge;
}
private void SetText(string str)
{
richTextBox1.AppendText(str); //文字列追加
if ((CommandNum == 7) || (CommandNum2 == 2))
{
str2 = str2 + str;
}
if (CommandNum == 8)
{
str3 = str;
}
if(CommandNum == 10)
{
str4 = str;
try
{
if (str4.IndexOf("Notify,000E,11") >= 0) //Notify,000E,10./ Notify,000E,11.の場合
{
if (str4[15] == '1') //SW1 : ONの場合
{
OnSw_pictureBox.Visible = true;
OffSw_pictureBox.Visible = false;
pictureBox5.Image = new Bitmap(pictureBox5.Width, pictureBox5.Height); //pictureBox1のイメージデータのオブジェクト生成
Graphics g = Graphics.FromImage(pictureBox5.Image); //イメージからグラフィックスを作成
g.FillEllipse(Brushes.Orange, 0, 0, 50, 50);//橙色塗りつぶし 基点(10,0) 幅×高さ:50×50
}
else //SW1:OFFの場合
{
OnSw_pictureBox.Visible = false;
OffSw_pictureBox.Visible = true;
pictureBox5.Image = new Bitmap(pictureBox5.Width, pictureBox5.Height); //pictureBox1のイメージデータのオブジェクト生成
Graphics g = Graphics.FromImage(pictureBox5.Image); //イメージからグラフィックスを作成
g.FillEllipse(Brushes.Gray, 0, 0, 50, 50);//灰色塗りつぶし 基点(10,0) 幅×高さ:50×50
}
}
//可変抵抗器VRのAD変換値処理
if (str4.IndexOf("Notify,000E,12") >= 0) //Notify,000E,12XXXX の場合
{
string strVR = str4[14].ToString() + str4[15].ToString() + str4[16].ToString() + str4[17].ToString();
int adcValue = Convert.ToInt32(strVR, 16);//16進数文字列を 10進数に変換
ADCMonitor((uint)adcValue); //プログレスバー表示、電圧値表示
}
//文字列返信の場合
if (str4.IndexOf("Notify,000E,13") >= 0) //Notify,000E,13XXXX の場合
{
string input = str4.Substring(str4.IndexOf("Notify,000E,13") + 14);
input = input.Replace(".", "");
input = input.Replace(" ", "");
input = input.Replace("\r", ""); //必須 これがないと後の16進文字列→標準文字列変換がうまく動作しない
input = input.Replace("\n", ""); //必須 これがないと後の16進文字列→標準文字列変換がうまく動作しない
int Num = 0;
int i;
byte[] array2 = new byte[input.Length / 2]; //shift-JIS バイト配列
for (i = 0; i < input.Length; i = i + 2)
{
string strXX = input.Substring(i, 2); //先頭からi番目から 2個づつ文字列化
array2[Num] = Convert.ToByte(strXX, 16); // 16進数文字列x2個を 標準文字x1個に変換
Num++;
}
byte[] byteUni = Encoding.Convert(encSjis, encUni, array2); //shift-jis からunicodeの配列に変換する
string strUni = encUni.GetString(byteUni); //配列を文字列に変換
richTextBox3.AppendText(strUni); //文字列追加
richTextBox3.AppendText("\n"); //改行
}
}
catch
{
}
}
//カレット位置を末尾に移動
richTextBox1.SelectionStart = richTextBox1.Text.Length;
//テキストボックスにフォーカスを移動
richTextBox1.Focus();
//カレット位置までスクロール
richTextBox1.ScrollToCaret();
if (str.IndexOf("Echo Off") != -1) Flag_EchoOff = 1; //"Echo Off"を含む文字列が返ってきたらFlag_EchoOff = 1;
}
private void ClearBtn_Click(object sender, EventArgs e)
{
richTextBox1.Clear();
}
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
byte[] byteRead = new byte[serialPort1.BytesToRead]; //受信文字
serialPort1.Read(byteRead, 0, serialPort1.BytesToRead);//読み込み
byte[] byteUni = Encoding.Convert(encSjis, encUni, byteRead); //shift-jis からunicodeに変換する
string strUni = encUni.GetString(byteUni); //配列を文字列に変換
ReceiveDelegate receiveDelegate = new ReceiveDelegate(SetText);
this.Invoke(receiveDelegate, strUni);
}
private void ComCBox_TextChanged(object sender, EventArgs e)
{
SendDataBtn.Visible = false;
if (serialPort1.IsOpen == true) // シリアルポートがオープンしている場合
{
serialPort1.Close(); //COMポートを閉じる
}
}
private void timer1_Tick(object sender, EventArgs e)
{
switch (CommandNum)
{
case 1:
if (Flag_EchoOff == 1) //"Echo Off"が戻ってきた場合 → Echo Onに変更
{
Flag_EchoOff = 0;
SendData("+//Echo OnOff");
CommandNum = 1;
break;
}
SendData("SF,1//Initialize RN4020");
timer1.Interval = 2000;
CommandNum++;
break;
case 2:
SendData("SR,80000000//Set Features, Central Mode"); //セントラルモード
CommandNum++;
break;
case 3:
SendData("SN,central_ysPC"); //デバイス名称設定
CommandNum++;
break;
case 4:
SendData("R,1//Reboot"); //RN4020 リブート
CommandNum++;
break;
case 5:
SendData("+//Echo OnOff"); //リブート後は Echo Offなので、Echo On に設定
CommandNum++;
break;
case 6:
CommandNum++;
SendData("F//Start Scan"); //スキャン開始
timer1.Interval = 4000;
break;
case 7:
CommandNum++;
timer1.Interval = 2000;
string[] array1 = str2.Split('\n'); //\nで分割、\nは削除される
List<string> list1 = new List<string>(array1); //リスト作成
list1.RemoveAll(strCheck); //条件にもとづくリスト作成
richTextBox2.AppendText(String.Join("\n", list1)); //リストを \n で結合し テキストボックスに表示);
break;
case 8:
if (str3 == "Connected\r\n") //★Retには\r\nが含まれている //接続完了まで待つ
{
timer1.Interval = 2000;//"Connected\r\n" 検出1000msec後 SW ON/OFF指令送信
CommandNum++;
SendData("LC//List Client Services");
}
break;
case 9:
//SWの状態変化、及びVRの電圧変化
SendData("CHW,000F,0100//Set Notification"); //ペリフェラルのキャラクタリスティックに書き込みがあった場合、
//セントラルに告知する。
//返信用の首都名の変化(上書き書き込み)
SendData("CHW,0015,0100//Set Notification"); //ペリフェラルのキャラクタリスティックに書き込みがあった場合、
//セントラルに告知する。
SendData("CHW,000B,10"); //LED3:OFF 初期値 初期LED3点灯対策
CommandNum++;
break;
case 10: //無限ループ
break;
default:
break;
}
}
private void ManuSendBtn_Click(object sender, EventArgs e) //手動コマンド送信ボタン
{
//serialPort1.DiscardInBuffer(); //受信バッファのデータクリア
//string strSend = SendDataCBox.Text;
//if (!strSend.EndsWith("\r")) strSend += "\r"; //改行が無かったら \rを追加する
//Byte[] byteArry = encSjis.GetBytes(strSend); //'送信文字をShift-jisに変換してをByte配列に格納
//serialPort1.Write(byteArry, 0, byteArry.Length); //送信
}
private void richTextBox1_SelectionChanged(object sender, EventArgs e)
{
//文字列
string str = richTextBox1.Text;
//カーソル位置を取得
int selectPos1 = richTextBox1.SelectionStart;
int selectPos = richTextBox1.SelectionStart;
//カーソルの位置までの行を数える
int row = 1, startPos = 0;
for (int endPos = 0;
(endPos = str.IndexOf('\n', startPos)) < selectPos && endPos > -1;
row++)
{
startPos = endPos + 1;
}
//列の計算
int col = selectPos - startPos + 1;
}
private void DeviceConnectBtn_Click(object sender, EventArgs e)
{
}
private void Re_ScanBtn_Click(object sender, EventArgs e)
{
//richTextBox2.Clear(); //Bluetooth デバイス一覧ボックス クリア
//str2 = "";
//serialPort1.DiscardInBuffer(); //受信バッファのデータクリア
//SendData("X//Stop Scan"); //スキャン停止
//timer2.Interval = 100;
//timer2.Enabled = true;
//CommandNum2 = 1;
}
private void richTextBox2_SelectionChanged_1(object sender, EventArgs e)
{
int CurrentPosi; //全文字列に於ける、カーソルの現在位置
int row; //カーソルの行位置
int startPosi; //str.IndexOf(char*, startPosi) 検索を開始する列位置
int endPosi;
int startPosi2 = 0; //str.IndexOf(char*, startPosi) 検索を開始する列位置
int endPosi2;
int Num = 0;
string DeviceName; //デバイス名
string str = richTextBox2.Text;
//全文字列における、カーソルの現在位置を取得
CurrentPosi = richTextBox2.SelectionStart; //カーソルの前にある全文字数(含む\n)を取得できる
// textBox1.Text = CurrentPosi.ToString(); //全文字列に於ける列の位置を表示
//カーソルの位置までの行を数える → 改行記号'\n'を数える
row = 1;
startPosi = 0;
for (endPosi = 0;
(endPosi = str.IndexOf('\n', startPosi)) < CurrentPosi && endPosi > -1; //str.IndexOf('\n', startPosi) →'\n'がある位置を返す
row++)
{
startPosi = endPosi + 1; //'\n'があった位置+1 → 次の行の先頭の文字位置
}
try
{
////表示
string strLine = richTextBox2.Lines[row - 1];//選択文字列
//////カーソル行の文字列の選択
////見つかった位置を選択開始の位置にする
richTextBox2.SelectionStart = startPosi;
////探した文字列の長さを選択する文字列の長さにする
richTextBox2.SelectionLength = strLine.Length;
//アドレス取得
strMacAdrs = strLine.Substring(0, 12);
textBox1.Text = strMacAdrs;
//アドレスタイプ取得 //パブリックアドレス:0 ランダムアドレス:1
strMacAdrsType = strLine.Substring(13, 1);
textBox4.Text = strMacAdrsType;
//デバイス名取得
int NameLength = strLine.IndexOf(',', 15) - 15; //デバイス名の長さ
if (NameLength == 0) DeviceName = "不明"; //長さ0の場合
else
{
DeviceName = strLine.Substring(15, NameLength);
}
textBox2.Text = DeviceName;
//電波強度取得
do
{
endPosi2 = strLine.IndexOf(",", startPosi2); //label3.Text = "指定文字列が ","x 4個以下の要素を削除の場合"";
if (endPosi2 >= 0)
{
startPosi2 = endPosi2 + 1;
Num++; //指定文字列の数をカウント
}
} while (Num != 4);
string dBmStr = strLine.Substring(endPosi2 + 1);
int dBm;
if (dBmStr[0] == '-') //負の場合 //1mW 以下の場合
{
dBmStr = dBmStr.Substring(1);
dBm = Convert.ToInt32(dBmStr, 16); //16進数文字列 → 10進整数
dBm = -dBm;
}
else dBm = Convert.ToInt32(dBmStr, 16); //正の場合 //1mW 以上の場合
textBox3.Text = dBm.ToString();
}
catch
{
}
}
private void DeviceConnectBtn_Click_1(object sender, EventArgs e)
{
string strTemp = "E," + strMacAdrsType + "," + strMacAdrs + "//Connect";
SendData(strTemp);
}
private void Re_ScanBtn_Click_1(object sender, EventArgs e)
{
richTextBox2.Clear(); //Bluetooth デバイス一覧ボックス クリア
str2 = "";
serialPort1.DiscardInBuffer(); //受信バッファのデータクリア
SendData("X//Stop Scan"); //スキャン停止
timer2.Interval = 100;
timer2.Enabled = true;
CommandNum2 = 1;
}
private void ManuSendBtn_Click_1(object sender, EventArgs e) //手動コマンド送信ボタン
{
serialPort1.DiscardInBuffer(); //受信バッファのデータクリア
string strSend = SendDataCBox.Text;
if (!strSend.EndsWith("\r")) strSend += "\r"; //改行が無かったら \rを追加する
Byte[] byteArry = encSjis.GetBytes(strSend); //'送信文字をShift-jisに変換してをByte配列に格納
serialPort1.Write(byteArry, 0, byteArry.Length); //送信
}
private void LedBtn_Click(object sender, EventArgs e)
{
string sendStr;
string LEDmode = "1";
if (AlternativeChar == '0') AlternativeChar = '1'; //呼ばれる毎に '0'/'1'を繰り返す
else AlternativeChar = '0';
if (LedMode == 0) //LED ONの場合
{
LedMode = 1;
sendStr = "CHW,000B," + LEDmode + AlternativeChar; //LED ON
SendData(sendStr);
LedBtn.BackColor = Color.OrangeRed;//オレンジ色
pictureBox1.Visible = true;
pictureBox2.Visible = false;
}
else
{
LedMode = 0; //LED OFFの場合
sendStr = "CHW,000B," + LEDmode + AlternativeChar; //LED OFF
SendData(sendStr);
LedBtn.BackColor = Color.DarkGray;//ダークグレー色
pictureBox1.Visible = false;
pictureBox2.Visible = true;
}
}
private void button1_Click(object sender, EventArgs e)
{
}
private void timer3_Tick(object sender, EventArgs e)
{
string sendStr;
if (AlternativeChar == '0') AlternativeChar = '1'; //呼ばれる毎に '0'/'1'を繰り返す
else AlternativeChar = '0';
if (LedMode == 0) sendStr = "CHW,000B," + AlternativeChar + "0"; //LED OFFの場合 Data[8] = 1
else sendStr = "CHW,000B," + AlternativeChar + "1"; //LED ONの場合 Data[8] = 1
SendData(sendStr);
}
private void timer2_Tick(object sender, EventArgs e)
{
switch (CommandNum2)
{
case 1:
SendData("F//Start Scan"); //スキャン開始 375 ms for scan interval, 250 ms for scan window
CommandNum2++;
timer2.Interval = 2000;
break;
case 2:
string[] array1 = str2.Split('\n'); //\nで分割、\nは削除される
List<string> list1 = new List<string>(array1); //リスト作成
list1.RemoveAll(strCheck); //条件にもとづくリスト作成
richTextBox2.AppendText(String.Join("\n", list1)); //リストを \n で結合し テキストボックスに表示);
CommandNum2 = 0;
timer2.Enabled = false;
break;
default:
break;
}
}
private string To_Hexadecimal(string input) //標準文字列 → 16進数表示文字列 変換関数
{
int[] num = new int[input.Length]; //shift-JIS整数値
string[] HexaDecimal = new string[input.Length]; //変換後の16進数文字列
byte[] array1 = encSjis.GetBytes(input); //'送信文字をShift-jisに変換してをByte配列に格納
for (int i = 0; i < array1.Length; i++)
{
num[i] = array1[i]; //配列
HexaDecimal[i] = num[i].ToString("X"); //大文字文字で表示
}
string ret = String.Join("", HexaDecimal); //区切り文字なしで文字列を結合
return ret;
}
private void SendDataBtn2_Click(object sender, EventArgs e)
{
try
{
serialPort1.DiscardInBuffer(); //受信バッファのデータクリア
string strStdData = SendDataCBox2.Text;
string strHexaData = To_Hexadecimal(strStdData); //標準文字列 → 16進数表示文字列 変換関数
string strTemp2 = "CHW,0011," + strHexaData; //0011:国名保存用 ペリフェラルキャラクタリスティックのハンドル
SendData(strTemp2); //\rを追加して送信
}
catch (Exception ex)
{
}
}
private void ClearReceiveStrBtn_Click(object sender, EventArgs e) //受信文字列表示リッチテキストボックスクリア
{
richTextBox3.Clear();
}
private void ADCMonitor(uint adcValue) //LEDの状態をモニタ //デリゲート用の関数を定義
{
int temp;
double Volt;
Volt = (adcValue * 3.3) / 4096;
VR_textBox.Text = string.Format("{0:f2} [V]", Volt); //小数点以下2桁にして表示
//四捨五入
temp = (int)((((float)adcValue * 100) / 4096) + 0.5); //0.5を足して、小数点以下を切り捨てる
VR_progressBar.Value = temp;
}
}
}